package cn.org.intelli.lims.o2oa.controller;

import cn.org.intelli.lims.o2oa.common.RestResult;
import cn.org.intelli.lims.o2oa.model.*;
import cn.org.intelli.lims.o2oa.repository.*;
import cn.org.intelli.lims.o2oa.service.O2oaService;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonObject;
import dm.jdbc.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.erupt.core.annotation.EruptRouter;
import xyz.erupt.core.constant.EruptRestPath;
import xyz.erupt.core.view.Page;
import xyz.erupt.core.view.TableQueryVo;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping(EruptRestPath.ERUPT_API + "/o2oa")
public class O2oaController {

    @Resource
    private PcaseRepository pcaseRepository;
    @Resource
    private JudicalLockerRepository judicalLockerRepository;
    @Resource
    private JudicalMaterialRepository judicalMaterialRepository;
    @Resource
    private PersonRepository personRepository;
    @Resource
    private JudicalMaterialOpRepository judicalMaterialOpRepository;
    @Resource
    private PcaseOpRepository pcaseOpRepository;
    @Resource
    private MaterialRepository materialRepository;
    @Resource
    private DeviceRepository deviceRepository;
    @Resource
    private MaterialOpRepository materialOpRepository;
    @Resource
    private DeviceOpRepository deviceOpRepository;
    @Autowired
    private O2oaService o2oaService;

    @PostMapping("/receive")
    @EruptRouter(verifyType = EruptRouter.VerifyType.MENU, authIndex = 1)
    public RestResult<String> receive(@RequestBody JsonObject data) {
        Pcase pcase = getPcaseDbRecorder(data.getAsJsonObject("weituo").get("id").getAsString());
        JudicalLocker judicalLocker = getJudicalLockerDbRecorder(data.getAsJsonObject("ccObj").get("id").getAsString());
        JudicalMaterial judicalMaterial = getJudicalMaterial(data, pcase, judicalLocker);
        judicalMaterialRepository.save(judicalMaterial);
        List<String> personIds = new ArrayList<>();
        data.get("jsr").getAsJsonArray().forEach(o -> personIds.add(((JsonObject) o).get("id").getAsString()));
        List<Person> persons = getPersonDbRecorders(personIds);
        List<JudicalMaterialOp> judicalMaterialOps = new ArrayList<>();
        List<PcaseOp> pcaseOps = new ArrayList<>();
        for (Person person : persons) {
            judicalMaterialOps.add(getJudicalMaterialOp(data, judicalMaterial, person));
            pcaseOps.add(getPcaseOp(pcase, "接收", person));
        }
        judicalMaterialOpRepository.saveAll(judicalMaterialOps);
        pcaseOpRepository.saveAll(pcaseOps);
        pcase.setStatus("待准备");
        pcase.setO2oaWorkid(data.get("id").getAsString());
        pcaseRepository.save(pcase);
        return RestResult.sucess("sucess");
    }

    @PostMapping("/prepare")
    @EruptRouter(verifyType = EruptRouter.VerifyType.MENU, authIndex = 1)
    public RestResult<String> prepare(@RequestBody JsonObject data) {
        Pcase pcase = getPcaseDbRecorder(data.get("id").getAsString());
        List<String> personIds = new ArrayList<>();
        data.get("zbUserList").getAsJsonArray().forEach(o -> personIds.add(((JsonObject) o).get("id").getAsString()));
        List<String> materialIds = new ArrayList<>();
        data.get("zbhcList").getAsJsonArray().forEach(o -> materialIds.add(((JsonObject) o).get("id").getAsString()));
        List<String> deviceIds = new ArrayList<>();
        data.get("zbcsList").getAsJsonArray().forEach(o -> deviceIds.add(((JsonObject) o).get("id").getAsString()));
        List<Person> persons = getPersonDbRecorders(personIds);
        List<Material> materials = getMaterialDbRecorders(materialIds);
        List<Device> devices = getDeviceDbRecorders(deviceIds);
        List<MaterialOp> materialOps = new ArrayList<>();
        List<DeviceOp> deviceOps = new ArrayList<>();
        List<PcaseOp> pcaseOps = new ArrayList<>();
        for (Person person : persons) {
            for (Material material : materials) {
                materialOps.add(getMaterialOp(material, pcase, person));
            }
            for (Device device : devices) {
                deviceOps.add(getDeviceOp(device, pcase, person));
            }
            pcaseOps.add(getPcaseOp(pcase, "准备", person));
        }
        materialOpRepository.saveAll(materialOps);
        deviceOpRepository.saveAll(deviceOps);
        pcaseOpRepository.saveAll(pcaseOps);
        pcase.setDevices(new HashSet<>(devices));
        pcase.setMaterials(new HashSet<>(materials));
        pcase.setStatus("待记录");
        pcaseRepository.save(pcase);
        return RestResult.sucess("sucess");
    }

    @PostMapping("/record")
    @EruptRouter(verifyType = EruptRouter.VerifyType.MENU, authIndex = 1)
    public RestResult<Object> record(@RequestBody JSONObject jsonObject) {
        Pcase pcase = getPcaseDbRecorder(jsonObject.get("id").toString());
        if (StringUtil.isEmpty(jsonObject.getString("inspection")) || StringUtil.isEmpty(jsonObject.getString("clientDepartment")) || StringUtil.isEmpty(jsonObject.getString("transferInspectPerson")) || StringUtil.isEmpty(jsonObject.getString("caseSerialNum")) || StringUtil.isEmpty(jsonObject.getString("acceptSerialNum")) || StringUtil.isEmpty(jsonObject.getString("entrustRequire")) || StringUtil.isEmpty(jsonObject.getString("briefCaseInfo")) || StringUtil.isEmpty(jsonObject.getString("orginAutDeptAndResult")) || StringUtil.isEmpty(jsonObject.getString("experimenter")) || StringUtil.isEmpty(jsonObject.getString("equipmentSerialNum")) || StringUtil.isEmpty(jsonObject.getString("equipmentName")) || StringUtil.isEmpty(jsonObject.getString("typeAndAmout")) || StringUtil.isEmpty(jsonObject.getString("stroageStatus")) || StringUtil.isEmpty(jsonObject.getString("place")) || StringUtil.isEmpty(jsonObject.getString("equipment")) || StringUtil.isEmpty(jsonObject.getString("consumableSerialNum")) || StringUtil.isEmpty(jsonObject.getString("consumableName")) || StringUtil.isEmpty(jsonObject.getString("consumableFactory")) || StringUtil.isEmpty(jsonObject.getString("performanceParameter")) || StringUtil.isEmpty(jsonObject.getString("methodSerialNum")) || StringUtil.isEmpty(jsonObject.getString("standardSerialNum")) || StringUtil.isEmpty(jsonObject.getString("processDescription")) || StringUtil.isEmpty(jsonObject.getString("inspectionData")) || StringUtil.isEmpty(jsonObject.getString("authenticateOpinion")) || StringUtil.isEmpty(jsonObject.getString("inspectPerson")) || StringUtil.isEmpty(jsonObject.getString("certigier"))) {
            return RestResult.fail("传递参数存在空值请检查");
        }
        RestResult<Object> result = o2oaService.generateDocReport(jsonObject.getString("inspection"), jsonObject.getString("clientDepartment"), jsonObject.getString("transferInspectPerson"), jsonObject.getString("caseSerialNum"), jsonObject.getString("acceptSerialNum"), jsonObject.getString("entrustRequire"), jsonObject.getString("briefCaseInfo"), jsonObject.getString("orginAutDeptAndResult"), jsonObject.getString("experimenter"), jsonObject.getString("equipmentSerialNum"), jsonObject.getString("equipmentName"), jsonObject.getString("typeAndAmout"), jsonObject.getString("stroageStatus"), jsonObject.getString("place"), jsonObject.getString("equipment"), jsonObject.getString("consumableSerialNum"), jsonObject.getString("consumableName"), jsonObject.getString("consumableFactory"), jsonObject.getString("performanceParameter"), jsonObject.getString("methodSerialNum"), jsonObject.getString("standardSerialNum"), jsonObject.getString("processDescription"), jsonObject.getString("inspectionData"), jsonObject.getString("authenticateOpinion"), jsonObject.getString("inspectPerson"), jsonObject.getString("certigier"));
        pcase.setStatus("已记录");
        pcaseRepository.save(pcase);
        return result;
        //return RestResult.sucess("sucess");
    }

    @PostMapping({"/demo"})
    @EruptRouter(verifyType = EruptRouter.VerifyType.MENU, authIndex = 1)
    public Page getDemoPersons(@RequestBody TableQueryVo tableQueryVo) {
        List<Person> perons = personRepository.findAll().stream().filter(person -> person.getTrains().stream().anyMatch(train -> train.getName().equals("上岗培训"))).collect(Collectors.toList());
        Page page = new Page();
        page.setPageIndex(1);
        page.setPageSize(10);
        page.setTotal(Long.valueOf(Integer.valueOf(perons.size()).toString()));
        page.setTotalPage(1);
        List<Map<String, Object>> datas = new ArrayList<>();
        for (Person person : perons) {
            Map<String, Object> data = new HashMap<>();
            data.put("org_name", person.getOrg().getName());
            data.put("name", person.getName());
            data.put("id", person.getId());
            datas.add(data);
        }
        page.setList(datas);
        return page;
    }

    private JudicalMaterial getJudicalMaterial(JsonObject data, Pcase pcase, JudicalLocker judicalLocker) {
        JudicalMaterial judicalMaterial = new JudicalMaterial();
        Optional.ofNullable(data.get("jcid").getAsString()).ifPresent(id -> judicalMaterial.setId(id));
        Optional.ofNullable(data.get("jcName").getAsString()).ifPresent(name -> judicalMaterial.setName(name));
        judicalMaterial.setPcase(pcase);
        judicalMaterial.setJudicalLocker(judicalLocker);
        Optional.ofNullable(data.get("sjr").getAsString()).ifPresent(fromPerson -> judicalMaterial.setFromPerson(fromPerson));
        Optional.ofNullable(data.get("sjTime").getAsString()).ifPresent(fromDate -> judicalMaterial.setFromDate(fromDate));
        Optional.ofNullable(data.get("jcType").getAsString()).ifPresent(type -> judicalMaterial.setType(type));
        return judicalMaterial;
    }

    private JudicalMaterialOp getJudicalMaterialOp(JsonObject data, JudicalMaterial judicalMaterial, Person person) {
        JudicalMaterialOp judicalMaterialOp = new JudicalMaterialOp();
        judicalMaterialOp.setId(UUID.randomUUID().toString());
        judicalMaterialOp.setJudicalMaterial(judicalMaterial);
        judicalMaterialOp.setPerson(person);
        judicalMaterialOp.setOpTime(new Date());
        return judicalMaterialOp;
    }

    private PcaseOp getPcaseOp(Pcase pcase, String stage, Person person) {
        PcaseOp pcaseOp = new PcaseOp();
        pcaseOp.setId(UUID.randomUUID().toString());
        pcaseOp.setPcase(pcase);
        pcaseOp.setStage(stage);
        pcaseOp.setPerson(person);
        pcaseOp.setOpTime(new Date());
        return pcaseOp;
    }

    private Pcase getPcaseDbRecorder(String pcaseId) {
        return Optional.ofNullable(pcaseId).map(id -> pcaseRepository.getById(id)).orElseGet(null);
    }

    private JudicalLocker getJudicalLockerDbRecorder(String judicalLockerId) {
        return Optional.ofNullable(judicalLockerId).map(id -> judicalLockerRepository.getById(id)).orElseGet(null);
    }

    private List<Person> getPersonDbRecorders(List<String> personIds) {
        return personIds.stream().filter(id -> id != null).map(id -> personRepository.getById(id)).collect(Collectors.toList());
    }

    private List<Material> getMaterialDbRecorders(List<String> materialIds) {
        return materialIds.stream().filter(id -> id != null).map(id -> materialRepository.getById(id)).collect(Collectors.toList());
    }

    private List<Device> getDeviceDbRecorders(List<String> deviceIds) {
        return deviceIds.stream().filter(id -> id != null).map(id -> deviceRepository.getById(id)).collect(Collectors.toList());
    }

    private MaterialOp getMaterialOp(Material material, Pcase pcase, Person person) {
        MaterialOp materialOp = new MaterialOp();
        materialOp.setId(UUID.randomUUID().toString());
        materialOp.setMaterial(material);
        materialOp.setPcase(pcase);
        materialOp.setPerson(person);
        materialOp.setOpTime(new Date());
        return materialOp;
    }

    private DeviceOp getDeviceOp(Device device, Pcase pcase, Person person) {
        DeviceOp deviceOp = new DeviceOp();
        deviceOp.setId(UUID.randomUUID().toString());
        deviceOp.setDevice(device);
        deviceOp.setPcase(pcase);
        deviceOp.setPerson(person);
        deviceOp.setOpTime(new Date());
        return deviceOp;
    }
}
